package com.yangrong.thirdservice.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.yangrong.common.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/oss")
public class OssController {

    @Autowired
    OSS ossClient;

    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;

    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;

    @Value("${spring.cloud.alicloud.secret-key}")
    private String secretId;


    @RequestMapping("/policy")
    public R policy() {
        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
        // callbackUrl为 上传回调服务器的URL，请将下面的IP和Port配置为您自己的真实信息。
//        String callbackUrl = "http://88.88.88.88:8888";
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; // 用户上传文件时指定的前缀。

        Map<String, String> respMap = null;
        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }

        return R.ok().put("data", respMap);
    }

    /**
     * 上传字符串
     *
     * @param content
     * @return
     */
    @RequestMapping("/uploadString")
    public R uploadString(@RequestParam String content) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String thisEndpoint = "http://" + endpoint;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = accessId;
        String accessKeySecret = secretId;
        String bucketName = bucket;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(thisEndpoint, accessKeyId, accessKeySecret);

        // 用户上传文件时指定的前缀。
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/" + UUID.randomUUID() + ".txt";
        // <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, dir, new ByteArrayInputStream(content.getBytes()));

        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        // ObjectMetadata metadata = new ObjectMetadata();
        // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        // metadata.setObjectAcl(CannedAccessControlList.Private);
        // putObjectRequest.setMetadata(metadata);

        // 上传字符串。
        ossClient.putObject(putObjectRequest);

        // 关闭OSSClient。
        ossClient.shutdown();

        return R.ok().put("articleSavePath", dir);
    }

    /**
     * 上传文件流
     *
     * @param filePath
     * @return
     */
    @RequestMapping("/uploadFile")
    public R uploadFile(@RequestParam String filePath) throws FileNotFoundException {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String thisEndpoint = "http://" + endpoint;
        // 云账号AccessKey有所有API访问权限，建议遵循阿里云安全最佳实践，创建并使用RAM子账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建。
        String accessKeyId = accessId;
        String accessKeySecret = secretId;
        String bucketName = bucket;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(thisEndpoint, accessKeyId, accessKeySecret);

        // 上传文件流。
        InputStream inputStream = new FileInputStream(filePath);
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; // 用户上传文件时指定的前缀。
        ossClient.putObject(bucketName, dir, inputStream);

        // 关闭OSSClient。
        ossClient.shutdown();

        return R.ok();
    }

    /**
     * 删除已上传文件
     *
     * @param params
     * @return
     */
    @RequestMapping("/delete")
    public R delete(@RequestParam Map<String, Object> params) {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String thisEndpoint = "http://" + endpoint;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = accessId;
        String accessKeySecret = secretId;
        String bucketName = bucket;
        String objectName = (String) params.get("objectName");

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(thisEndpoint, accessKeyId, accessKeySecret);

        // 删除文件。如需删除文件夹，请将ObjectName设置为对应的文件夹名称。如果文件夹非空，则需要将文件夹下的所有object删除后才能删除该文件夹。
        ossClient.deleteObject(bucketName, objectName);

        // 关闭OSSClient。
        ossClient.shutdown();
        return R.ok();
    }

    /**
     * 读取远程文件
     *
     * @param params
     * @return
     */
    @RequestMapping("/read")
    public R read(@RequestParam Map<String, Object> params) throws IOException {
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String thisEndpoint = "http://" + endpoint;
        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        String accessKeyId = accessId;
        String accessKeySecret = secretId;
        String bucketName = bucket;
        //<yourObjectName>表示从OSS下载文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        String objectName = (String) params.get("objectName");

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(thisEndpoint, accessKeyId, accessKeySecret);

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);

        StringBuilder builder = new StringBuilder();
        // 读取文件内容。
//        System.out.println("Object content:");
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        while (true) {
            String line = reader.readLine();
            if (line != null && !"null".equals(line) && !"".equals(line))
                builder.append(line);
            if (line == null) break;
//            System.out.println("\n" + line);
        }
        // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
        reader.close();

        // 关闭OSSClient。
        ossClient.shutdown();

        return R.ok().put("content", builder.toString());
    }

}
